import json

from fastapi import  APIRouter,Response
from pydantic import BaseModel
import os
import sys
import yaml
from PIL import Image
import numpy as np
import xml.etree.ElementTree as ET

deviceDetail_router = APIRouter()

class deviceVersion(BaseModel):
    device: str
@deviceDetail_router.get('/deviceDetail')#获取所有设备列表
async def get_deviceDetail():
    # 示例调用
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path = os.path.join(BASE_DIR, 'app/config/yml')
    re = get_all_files_recursive(path)
    files=[]
    for i in re:
        f=os.path.splitext(i)[0]
        files.append(f)
    #对files进行排序，不识别大小写
    files.sort(key=lambda x: x.split('.')[0].lower())
    return files

def get_all_files_recursive(path: str) -> list:
    # """
    # 递归获取指定目录下的所有文件名（含子目录）
    # :param path: 目录路径（相对/绝对）
    # :return: 完整文件路径列表（含所有子目录的文件）
    # """
    try:
        all_files = []
        # 遍历目录树（递归）
        for dirpath, dirnames, filenames in os.walk(path):
            # 遍历当前目录下的所有文件
            for filename in filenames:
                # 构造完整文件路径（推荐，避免路径歧义）
                all_files.append(filename)
        return all_files
    except OSError as e:
        print(f"错误：无法访问目录 {path} - {e}")
        return []
def get_svg_image(path):
    # 1. 解析SVG文件
    tree = ET.parse(path)
    root = tree.getroot()  # 根元素<svg>
    # 2. 优先读取<svg>元素的width/height属性
    width = root.get("width")
    height = root.get("height")
    width = _parse_unit(width)
    height = _parse_unit(height)
    return width, height
def _parse_unit(value):
    # """
    # 处理带单位的数值（如"100px"→100，"50%"→50，"12.5em"→12.5）
    # :param value: 带单位的字符串（如"100px"）或数值（如100）
    # :return: 转换后的数值→若无法转换，返回None
    # """
    if value is None:
        return None
    if isinstance(value, (int, float)):
        return float(value)

    # 去除空格（如" 100 px "→"100px"）
    value = value.strip()
    if not value:
        return None

    # 处理百分比（如"50%"→50）
    if value.endswith("%"):
        try:
            return float(value[:-1])
        except ValueError:
            return None

    # 处理像素（如"100px"→100）
    if value.endswith("px"):
        try:
            return value[:-2]
        except ValueError:
            return None

    # 处理其他单位（如"12.5em"→12.5，"20cm"→20）→ 简化处理，直接取数值部分
    try:
        # 提取数值部分（如"12.5em"→"12.5"）
        numeric_part = "".join([c for c in value if c.isdigit() or c in ".+-"])
        return numeric_part if numeric_part else None
    except ValueError:
        return None
def get_pgwh_list(path):
    all_files = get_all_files_recursive(path)
    pgwh_list=[]
    for i in all_files:
        image_path = os.path.join(path, i)
        ext = os.path.splitext(image_path)[1]
        if ext not in ('.png', '.jpg', '.jpeg', '.bmp'):
            width, height = get_svg_image(image_path)
            pgwh = {
                'name': i, 
                'width': int(width),
                'height': int(height)
                }
            pgwh_list.append(pgwh)
        else:
            img = Image.open(image_path)
            cv_img = np.array(img)
            pgwh = {'name': i, 'width': cv_img.shape[1], 'height': cv_img.shape[0]}
            pgwh_list.append(pgwh)
    return pgwh_list

@deviceDetail_router.get('/deviceIcon')
async def get_deviceIcon():
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path = os.path.join(BASE_DIR, 'app/static/icon')
    pgwh_list=get_pgwh_list(path)
    #对pgwh_list进行排序，不识别大小写
    pgwh_list.sort(key=lambda x: x['name'].lower())   
    responses = Response(json.dumps(pgwh_list),status_code=200)
    return responses

@deviceDetail_router.get('/neticon')
async def get_neticon():
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path = os.path.join(BASE_DIR, 'app/static/net_icons')
    pgwh_list=get_pgwh_list(path)   
    pgwh_list.sort(key=lambda x: x['name'].lower())
    responses = Response(json.dumps(pgwh_list),status_code=200)
    return responses

#获取对应设备的版本
def get_version(name):
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path = os.path.join(BASE_DIR, 'app/qcow2/qemu')
    entries = os.listdir(path)
    folders = [entry for entry in entries if os.path.isdir(os.path.join(path, entry))]
    return [entry for entry in folders if entry.startswith(name)]
@deviceDetail_router.get('/deviceVersion')
async def get_deviceVersion(device:str):
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path=os.path.join(BASE_DIR, f'app/config/yml/{device}.yml')
    with open(path, 'r', encoding='utf-8') as f:
        data =  yaml.safe_load(f.read())
    cpu = data.get("cpu")
    ram = data.get("ram")
    ethernet = data.get("ethernet")
    eth_name = data.get('eth_name')
    eth_type = data.get('eth_format')
    icon = data.get('icon')
    modelDetail = get_version(device)
    #需要判断icon是否在icon文件夹下
    if not os.path.exists(os.path.join(BASE_DIR, 'app/static/icon/'+icon)):
        icon = 'Router-2D-Gen-Grey-S.svg'
    image_path = os.path.join(BASE_DIR, 'app/static/icon/'+icon)
    ext = os.path.splitext(image_path)[1]
    if ext not in ('.png', '.jpg', '.jpeg', '.bmp'):
        width, height = get_svg_image(image_path)
        pgwh = {'name':icon,'width': int(width),'height': int(height)}
    else:
        img = Image.open(image_path)
        cv_img = np.array(img)
        pgwh = {'name':icon,'width': cv_img.shape[1], 'height': cv_img.shape[0]}
    console = data.get('console')
    responses = Response(json.dumps({'modelDetail':modelDetail,'cpu':cpu,'ram':ram,'ethernet':ethernet,'eth_name':eth_name,'eth_type':eth_type,'icon':pgwh,'console':console}),status_code=200)
    return responses

@deviceDetail_router.get('/deviceExist')#查找存在的设备
async def get_deviceExist():
    BASE_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
    path = os.path.join(BASE_DIR, 'app/qcow2/qemu')
    entries = os.listdir(path)
    folders = [entry for entry in entries if os.path.isdir(os.path.join(path, entry))]
    res = [entry.split('-')[0] for entry in folders if '-' in entry]
    responses = Response(json.dumps(res),status_code=200)
    return responses
























